package com.example.siteservices.util;

import cn.hutool.core.codec.Base64;
import org.apache.commons.lang3.RandomUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.util.Assert;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.Security;

public class EncrypDataUtil {
    public static final String AES_ALGORITHM = "AES/CBC/PKCS7Padding";
    public static final String CHAR_ENCODING = "UTF-8";

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 加密
     *
     * @param data 需要加密的内容
     * @param key  加密密码
     * @return
     */
    public static byte[] encrypt(byte[] data, byte[] key, byte[] iv) {
        Assert.notNull(data, "The data is empty");
        Assert.notNull(key, "The key is empty");
        if (key.length != 16) {
            throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
        }
        try {
            SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance(AES_ALGORITHM, "BC"); // 指定使用BouncyCastle提供者
            IvParameterSpec initVector = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, seckey, initVector);
            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("encrypt fail!", e);
        }
    }

    /**
     * 解密
     *
     * @param data 待解密内容
     * @param key  解密密钥
     * @return
     */
    public static byte[] decrypt(byte[] data, byte[] key, byte[] iv) {
        Assert.notNull(data, "The data is empty");
        Assert.notNull(key, "The key is empty");
//        if (key.length != 16) {
//            throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
//        }
        try {
            SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance(AES_ALGORITHM, "BC"); // 指定使用BouncyCastle提供者
            IvParameterSpec initVector = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, seckey, initVector);
            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("decrypt fail!", e);
        }
    }

    public static byte[] generateRandomKey() {
        return RandomUtils.nextBytes(16);
    }


    /**
     * 加密Base64数据
     * @param data 明文(base64)
     * @param key iv(base64)
     * @return 密文(base64)
     */
    public static String encryptWithBase64(String data, byte[] key, byte[] iv) {
        try {
            byte[] valueByte = encrypt(data.getBytes(CHAR_ENCODING), key, iv);
            return Base64.encode(valueByte);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("encrypt fail!", e);
        }
    }


    public static String decryptWithBase64(String data, byte[] key, byte[] iv) {
        try {
            byte[] originalData = Base64.decode(data.getBytes());
            byte[] valueByte = decrypt(originalData, key, iv);
            return new String(valueByte, CHAR_ENCODING);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("decrypt fail!", e);
        }
    }
}
